import { Application, ServerInfo } from "mydog";
import { DEF } from "./definition/consts";
import { Dictionary } from "./definition/interface";
import Jwt from "jsonwebtoken"

class GateManager {

  private static _instance: GateManager | undefined = undefined;
  public static getInstance(): GateManager {
    if (!this._instance) {
      this._instance = new GateManager();
    }
    return this._instance;
  }

  private constructor() { }

  private _app: Application = null as any;
  private _minServer: ServerInfo = null as any;
  private _userToken: Dictionary<string> = {};

  public init(app: Application) {
    this._app = app;

    setTimeout(this.checkMinServer.bind(this), 1000);
    // 定时获取网关服人数
    setInterval(async () => {
      const connectors = this._app.getServersByType(DEF.SEVER.TYPE.CONNECTOR);
      for (let one of connectors) {
        one.userNum = await this._app.rpc(one.id).connector.main.getOnlineNum();
      }
      this.checkMinServer();
    }, 5000);
  }

  public getConnectorServer() {
    // if (!this._app.getServerById(this._minServer.id)) {
    //   this.checkMinServer();
    // }

    this.checkMinServer();

    return this._minServer;
  }

  public tokenSign(uid: number) {
    try {
      const token = Jwt.sign({ uid }, DEF.SYSTEM.TOKEN.SECRET_OR_PRIVATE_KEY, { expiresIn: DEF.SYSTEM.TOKEN.EXPIRES_IN });
      this._userToken[uid] = token;
      return token;
    } catch (error) {
      console.log(error);
      return '';
    }
  }

  public async tokenVerify(uid: number, token: string) {
    return await new Promise<boolean>((resolve, reject) => {
      Jwt.verify(token, DEF.SYSTEM.TOKEN.SECRET_OR_PRIVATE_KEY, (err, data) => {
        if (!!err) {
          reject(false);
          return;
        }
        if (!!data) {
          resolve(data.uid === uid);
          return;
        }
      })
    })
  }

  // 设置最低负载网关
  private checkMinServer() {
    const connectors = this._app.getServersByType(DEF.SEVER.TYPE.CONNECTOR);
    let minServer = connectors[0];
    minServer.userCount = minServer.userCount || 0;
    for (let one of connectors) {
      one.userNum = one.userNum || 0;
      if (one.userNum < minServer.userNum) {
        minServer = one;
      }
    }
    this._minServer = minServer;
  }
}

export default GateManager.getInstance();
